import axios from 'axios'
import Vue from 'vue'
import util from './util'
import api from './api'
import eventBus from './event-bus'
import Api from '../../build/config'
import { faceFileApi } from './const'

// 本地开发全部走node代理
let apiBasePath = '/v3/'
let apiLoginPath = '/'

// 服务器环境全部走绝对路径
if (process && process.env) {
//   if (process.env.NODE_ENV === 'production') {
//     apiLoginPath = '/'
//   }
//   if (process.env.NODE_ENV === 'test') {
  apiLoginPath =
    (process.env.ENV === 'online') ? Api.passport + '/' : '/'
  //   }
  apiBasePath =
    process.env.ENV === 'local' || process.env.ENV === 'localhost' || process.env.ENV === 'release'
      ? '/v3/'
      : Api.sass + '/v3/'
}

// console.log('NODE_ENV', process.env.NODE_ENV, 'ENV', process.env.ENV);

// http请求方式
const methods = {
  DELETE: 'delete',
  GET: 'get',
  OPTIONS: 'options',
  PATCH: 'patch',
  POST: 'post',
  PUT: 'put'
}

// 错误信息
const errMsgs = {
  '400': '参数错误(400)',
  '401': '权限受限(401)',
  '500': '服务器报错(500)',
  '504': '网关超时(504)'
}

let http = {}

http.fillApi = function (apiPath, routeParams) {
  const apiPathArr = apiPath.split('/')
  const patt = /:/
  const params = Array.isArray(routeParams) ? [ ...routeParams ] : []

  if (!patt.test(apiPath)) {
    return apiPath
  }

  if (!params || !params.length) {
    http.messageError(apiPath, '缺少api参数')
    return null
  }

  for (let i in apiPathArr) {
    if (patt.test(apiPathArr[i])) {
      if (!params.length) {
        http.messageError(apiPath, `缺少参数${apiPathArr[i]}`)
        return null
      }
      apiPathArr[i] = params.shift()
    }
  }
  return apiPathArr.join('/')
}

/**
 * 限制报错频率
 */
function _message_error (delay) {
  let last = 0
  let lastMsg = ''
  return function (apiPath, msg) {
    let curr = +new Date()
    if (curr - last > delay || msg !== lastMsg) {
      util.log('-----------last error msg----------', lastMsg)
      Vue.prototype.$Message.error(msg)
      last = curr
      lastMsg = msg
    }
  }
}

/**
 * 限制报错频率
 * 同一api 3s内只能报错一次
 */
http.messageError = _message_error(3000)

/**
 * 格式化参数
 * @param {Object} params 参数
 */
http.formatParams = function (params) {
  let item
  for (let i in params) {
    item = params[i]

    if (util.isArray(item) && !item.length) {
      delete params[i]
    }

    if (!!item && typeof item === 'object') {
      http.formatParams(item)
    }
  }
}

/**
 * 格式化参数
 * 导出报表用，多加了去掉空字符串
 * @param {Object} params 参数
 */
http.formatParams2 = function (params) {
  let item
  for (let i in params) {
    item = params[i]
    if (item !== 0 && !item) {
      delete params[i]
    }

    if (util.isArray(item) && !item.length) {
      delete params[i]
    }

    if (!!item && typeof item === 'object') {
      http.formatParams2(item)
    }
  }
}

/**
 * 导出表格
 * @param {String} vm
 * @param {Object} apiObj api对象
 * @param {Array} routeParams PATH参数 [12,3]
 * @param {Object} data 请求参数
 *
 */
http.exportTable = function (vm, apiObj, routeParams, params) {
  let apiPath = apiObj.path
  let apiPathOri = apiPath

  if (!apiPath) {
    http.messageError(apiPathOri, '无此api')
    return
  }
  apiPath = http.fillApi(apiPath, routeParams)

  if (!apiPath) {
    return
  }

  apiPath = apiPath !== api.login.path ? apiBasePath + apiPath : apiPath

  http.formatParams2(params)

  const queryString = Object.keys(params).reduce((result, key) => {
    const queryValue = params[key]

    result += (result === '' ? '?' : '&') + `${key}=${queryValue}`
    return result
  }, '')

  window.open(apiPath + queryString)
}

/**
 *  await版本消息请求
 * @param {String} vm
 * @param {Object} apiObj api对象
 * @param {String} method 请求方法
 * @param {JSON} data 请求参数
 * @param {Bool} isHideErrToast 是否隐藏错误提示
 * let res = await http.request(api.login, [11, 22], {name:'test'})
 */

http.req = async function (apiObj, routeParams = null, params = null, isHideErrMsg = false) {
  let apiPath = apiObj.path
  let apiPathOri = apiPath
  let method = apiObj.method

  if (!apiPath) {
    http.messageError(apiPathOri, '无此api')
    return
  }

  apiPath = http.fillApi(apiPath, routeParams)

  if (!apiPath) {
    return
  }

  apiPath = apiPath !== api.login.path ? apiBasePath + apiPath : apiLoginPath + apiPath

  http.formatParams(params)

  let config = {
    method: method,
    url: apiPath,
    withCredentials: true
  }

  if (method === methods.GET || method === methods.DELETE) {
    config.params = params
  }

  if (method !== methods.GET) {
    config.data = params
  }

  try {
    let res = await axios(config)

    let {
      data: { err_code, err_msg, result }
    } = res

    if (err_code) {
      // 如果出现错误码
      if (err_code === 4007 || err_code === 4018) {
        http.messageError(apiPathOri, errMsgs[err_code])
        http.logout(1500)
      }

      if (!isHideErrMsg) http.messageError(apiPathOri, err_msg)

      return
    }

    return result // 如果result存在就返回result，没有的话就直接返回result
  } catch (err) {
    console.log(err)
    if (!err.response) {
      return
    }

    let {
      data: { err_msg, err_code }
    } = err.response

    if (err_msg && !isHideErrMsg) {
      // http请求出问题提示状态码
      http.messageError(apiPathOri, err_msg)
    }

    if (err_code === 401002) {
      // 当后端返回状态吗是401002，退出登陆
      http.logout(500)
    }
  }
}

/**
 * 消息请求
 * @param {String} vm
 * @param {Object} apiObj api对象
 * @param {String} method 请求方法
 * @param {JSON} data 请求参数
 * @param {Function} cb 回调函数
 * @param {Bool} isHideErrToast 是否隐藏错误提示
 * http.request(this, api.login, [11, 22], {name:'test'}, (res, err) => {
 * });
 */
http.request = function (vm, apiObj, routeParams, params, cb, isHideErrMsg, useFormData = false) {
  let apiPath = apiObj.path
  let apiPathOri = apiPath
  let method = apiObj.method

  if (!apiPath) {
    http.messageError(apiPathOri, '无此api')
    return
  }

  // let regions = http.getRegions(apiPath, params);
  // if (regions) {
  //     typeof cb === 'function' && cb(regions, null);
  //     return;
  // }

  apiPath = http.fillApi(apiPath, routeParams)

  if (!apiPath) {
    return
  }

  if (apiObj.path === 'inner/face_files/:face_file_id') {
    apiPath = faceFileApi + '/v1/' + apiPath
  } else {
    apiPath =
            apiPath !== api.login.path
              ? apiBasePath + apiPath
              : apiLoginPath + apiPath
  }

  http.formatParams(params)

  let config = {
    method: method,
    url: apiPath,
    withCredentials: true
  }

  if (useFormData) {
    config.headers = {
      'Content-Type': 'multipart/form-data'
    }
  }

  if (
    apiObj === api.login_information_check ||
        apiObj === api.login_token_get
  ) {
    delete config.headers
  }

  if (method === methods.GET || method === methods.DELETE) {
    config.params = params
  }

  if (method !== methods.GET) {
    config.data = params
  }

  axios(config)
    .then(res => {
      // let resRemoveGetter = JSON.parse(JSON.stringify(res))
      // util.log(apiPath, 'rsp:', resRemoveGetter.data);

      let resData = res.data

      if (resData.err_code) {
        if (resData.err_code === 4007 || resData.err_code === 4018) {
          http.messageError(apiPathOri, errMsgs[resData.err_code])
          http.logout(1500)
        }

        typeof cb === 'function' && cb(null, res)
        !isHideErrMsg && http.messageError(apiPathOri, resData.err_msg)
        return
      }

      typeof cb === 'function' && cb(resData.result ? resData.result : resData, null)
    })
    .catch(err => {
      util.log(apiPath, 'err:', err, err.response)

      let res = err.response
      typeof cb === 'function' && cb(null, res)

      if (!res) {
        return
      }

      // let status = res.status;

      // if (status && errMsgs[status]) {
      //     http.messageError(vm,apiPath,errMsgs[status]);
      // }
      if (res.data && res.data.err_msg && !isHideErrMsg) {
        http.messageError(apiPathOri, res.data.err_msg)
      }

      if (res.data && res.data.err_code === 401002) {
        http.logout(500)
      }
    })
}

/**
 * 设置区域
 * @param {String} apiPath api名称
 */
http.setRegions = function (apiPath, params, res) {
  apiPath = apiPath.replace(apiBasePath, '')

  if (!res) {
    return
  }

  let allItem = { id: 0, name: '全部', short_name: '全部', region_code: 0 }

  switch (apiPath) {
    case api.address_provinces.path:
      res.unshift(allItem)
      http.provinces = res
      return res
    case api.address_cities.path:
      res.unshift(allItem)
      let cities = http.cities || {}
      if (params && params.province_id) {
        cities[params.province_id] = res
      } else {
        cities['all'] = res
      }
      http.cities = cities
      return res
    case api.address_districts.path:
      res.unshift(allItem)
      let districts = http.districts || {}
      if (params && params.city_id) {
        districts[params.city_id] = res
        http.districts = districts
      }
      return res
  }

  return null
}

/**
 * 获取区域
 * @param {String} apiPath api名称
 */
http.getRegions = function (apiPath, params) {
  if (apiPath === api.address_provinces.path && http.provinces) {
    return http.provinces
  }

  if (apiPath === api.address_cities.path && http.cities) {
    util.log('http.cities:', http.cities)
    if (params && params.province_id) {
      return http.cities[params.province_id]
    }
    return http.cities.all
  }

  if (apiPath === api.address_districts.path && params && params.city_id && http.districts) {
    return http.districts[params.city_id]
  }

  return null
}

/**
 * 退出
 * @param {Number} delay 延迟时间
 */
http.logout = function (delay = 0) {
  eventBus.$emit('logout')
}

http.fetch = function (vm, apiObj, routeParams = null, params = null, noError = false) {
  return new Promise((resolve, reject) => {
    http.request(
      vm,
      apiObj,
      routeParams,
      params,
      (res, err) => {
        if (err || !res) {
          reject(err)
        }
        resolve(res)
      },
      noError
    )
  })
}
module.exports = {
  http,
  methods,
  api
}
